#pragma once
#include "types.hpp"
#include <functional>


enum LIGHTSOURCE_TYPE { LIGHTSOURCE_POINT, LIGHTSOURCE_RAY, LIGHTSOURCE_AREA, 
        LIGHTSOURCE_GAUSSIAN, LIGHTSOURCE_STRUCTURE };

double constantPulse(double t);


class LightSource
{
public:
    LightSource();
    LightSource(int enumType, bool isPolarized, bool isPhase, bool isTime, Point3d centralPosition, 
            Vec3d centralDirection, double waveLength, double photonsPerJoule, double timeScale, double tp, 
            std::function<double(double)> pulseShape, double divengencyAngle, double sourceArea);
    LightSource(const LightSource& ls);
    LightSource& operator=(const LightSource &ls);
public:
    int enumType;               // light source type
    bool isPolarized;           // polarization?
    bool isPhase;               // phase variant?
    bool isTime;                // time variant?
    Point3d centralPosition;    // central position of light source
    Vec3d centralDirection;     // central direction of light source
    double waveLength;          // wavelength of light
    double photonsPerJoule;     // sampling rate, photon number / pulse energy (joule)

    // for time variant source
    double timeScale;           // time step of input time-intensity array
    double tp;                  // pulse time
    std::function<double(double)> pulseShape;   // pulse shape function

    // spatial parameters
    double divengencyAngle;     // divengency angle of light source, deg
    double sourceArea;          // area of light source area, for gaussian and area type
};


LightSource::LightSource()
{
    enumType = LIGHTSOURCE_POINT;
    isPolarized = false;
    isPhase = false;
    isTime = false;
    centralPosition = Point3d::Point3(0,0,0);
    centralDirection = Point3d::Point3(0,0,1);
    waveLength = 532;
    photonsPerJoule = 0;
    timeScale = 0;
    tp = 5.0e-9;
    pulseShape = constantPulse;
    divengencyAngle = 60;
    sourceArea = 0;
}


LightSource::LightSource(int enumType, bool isPolarized, bool isPhase, bool isTime, Point3d centralPosition, 
            Vec3d centralDirection, double waveLength, double photonsPerJoule, double timeScale, double tp, 
            std::function<double(double)> pulseShape, double divengencyAngle, double sourceArea)
{
    this->enumType = enumType;
    this->isPolarized = isPolarized;
    this->isPhase = isPhase;
    this->isTime = isTime;
    this->centralPosition = centralPosition;
    this->centralDirection = centralDirection;
    this->waveLength = waveLength;
    this->photonsPerJoule = photonsPerJoule;
    this->timeScale = timeScale;
    this->tp = tp;
    this->pulseShape = pulseShape;
    this->divengencyAngle = divengencyAngle;
    this->sourceArea = sourceArea;
}

LightSource::LightSource(const LightSource& ls)
{
    this->enumType = ls.enumType;
    this->isPolarized = ls.isPolarized;
    this->isPhase = ls.isPhase;
    this->isTime = ls.isTime;
    this->centralPosition = ls.centralPosition;
    this->centralDirection = ls.centralDirection;
    this->waveLength = ls.waveLength;
    this->photonsPerJoule = ls.photonsPerJoule;
    this->timeScale = ls.timeScale;
    this->tp = ls.tp;
    this->pulseShape = ls.pulseShape;
    this->divengencyAngle = ls.divengencyAngle;
    this->sourceArea = ls.sourceArea;
}


LightSource& LightSource::operator=(const LightSource &ls)
{
    this->enumType = ls.enumType;
    this->isPolarized = ls.isPolarized;
    this->isPhase = ls.isPhase;
    this->isTime = ls.isTime;
    this->centralPosition = ls.centralPosition;
    this->centralDirection = ls.centralDirection;
    this->waveLength = ls.waveLength;
    this->photonsPerJoule = ls.photonsPerJoule;
    this->timeScale = ls.timeScale;
    this->tp = ls.tp;
    this->pulseShape = ls.pulseShape;
    this->divengencyAngle = ls.divengencyAngle;
    this->sourceArea = ls.sourceArea;
    return *this;
}


double constantPulse(double t)
{
    return 1.0;
}

